#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string>
#include "conf.h"
#include "work.h"
#include "httpd.h"

using namespace std;

struct MHD_Daemon *server;

/* http响应函数 */
int httpd_handler(void *cls, struct MHD_Connection *connection,
                  const char *url, const char *method,
                  const char *version, const char *upload_data,
                  size_t *upload_data_size, void **ptr);

/* 主页面响应 */
int httpd_main_page(struct MHD_Connection *connection);
/* PDF传输 */
int httpd_pdf(struct MHD_Connection *connection);
/* json修改 */
int httpd_json(struct MHD_Connection *connection, const char *json);

int httpd_init()
{
    /* 获取监听端口 */
    int port = conf_get_port();
    /* 启动http服务 */
    server = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, port, NULL, NULL,
                              httpd_handler, NULL, MHD_OPTION_END);
    if(NULL == server)
    {
        puts("ERROR: Can't start http service!");
        return -1;
    }
    printf("listening at %d port\n", conf_get_port());
    return 0;
}

void httpd_kill()
{
    if(NULL != server)
    {
        MHD_stop_daemon(server);
    }
}

/* http响应函数 */
int httpd_handler(void *cls, struct MHD_Connection *connection,
                  const char *url, const char *method,
                  const char *version, const char *upload_data,
                  size_t *upload_data_size, void **con_cls)
{
    static int dummy;

    if(0 != strcmp(method, "GET")) return MHD_NO;
    /* 仅处理GET请求 */

    /* 首次数据包只有 header， 不发送响应数据包 */
    if (&dummy != *con_cls)
    {
        *con_cls = &dummy;
        return MHD_YES;
    }

    /* GET请求不允许上传数据 */
    if(0 != *upload_data_size) return MHD_NO;

    if(0 == strcmp(url, "/"))
    {
        /* 主页面响应 */
        return httpd_main_page(connection);
    }
    if(0 == strcmp(url, "/analysisRet"))
    {
        /* 传输PDF */
        return httpd_pdf(connection);
    }
    if(0 == strncmp(url, "/setting=", strlen("/setting=")))
    {
        /* 设置更改 */
        return httpd_json(connection, url + strlen("/setting="));
    }

    return MHD_NO;
}

/* 主页面响应 */
int httpd_main_page(struct MHD_Connection *connection)
{
    const char *main_page = "<html><head><title>LAW - Home</title>"
             "</head><body><a href=\"analysisRet\">Click to show analysis result</a></body></html>";
    int ret;
    struct MHD_Response *res;
    res = MHD_create_response_from_buffer(strlen(main_page), (void *)main_page, MHD_RESPMEM_PERSISTENT);
    if(NULL == res) return MHD_NO;
    ret = MHD_queue_response(connection, MHD_HTTP_OK, res);
    MHD_destroy_response(res);
    return ret;
}

/* PDF传输 */
int httpd_pdf(struct MHD_Connection *connection)
{
    string filename = work_out_pdf();
    int fd;
    struct stat sbuf;
    /* 打开文件PDF失败，回到主页面 */
    if(-1 == (fd = open(filename.c_str(), O_RDONLY))) return httpd_main_page(connection);
    if(0 != fstat(fd, &sbuf))
    {
        close(fd);
        return httpd_main_page(connection);
    }
    int ret;
    struct MHD_Response *res;
    res = MHD_create_response_from_fd_at_offset64(sbuf.st_size, fd, 0);
    if(NULL == res)
    {
        close(fd);
        return MHD_NO;
    }
    MHD_add_response_header(res, "Content-Type", "application/pdf");
    ret = MHD_queue_response(connection, MHD_HTTP_OK, res);
    MHD_destroy_response(res);
    return ret;
}

/* json修改 */
int httpd_json(struct MHD_Connection *connection, const char *json)
{
    puts(json);
    const char *json_page = "<html><head><title>LAW - Setting</title>"
             "</head><body>New settings applyed</body></html>";
    
    /* 修改设置 */
    conf_change(json);
    
    int ret;
    struct MHD_Response *res;
    res = MHD_create_response_from_buffer(strlen(json_page), (void *)json_page, MHD_RESPMEM_PERSISTENT);
    if(NULL == res) return MHD_NO;
    ret = MHD_queue_response(connection, MHD_HTTP_OK, res);
    MHD_destroy_response(res);
    return ret;
}